package org.mall.modules.pay.controller.users;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.mall.common.api.vo.CommonResult;
import org.mall.common.constant.*;
import org.mall.common.system.util.JwtUtil;
import org.mall.common.util.DateUtils;
import org.mall.common.util.HttpUtil;
import org.mall.common.util.json.JacksonUtils;
import org.mall.modules.message.service.AppMessageService;
import org.mall.modules.pay.dataobject.PayNotifyTaskDO;
import org.mall.modules.pay.dataobject.PayTransactionDO;
import org.mall.modules.pay.dataobject.PayTransactionExtensionDO;
import org.mall.modules.pay.service.PayTransactionService;
import org.mall.modules.pay.service.impl.PayNotifyServiceImpl;
import org.mall.modules.pojo.common.AppMessageDTO;
import org.mall.modules.pojo.pay.message.PayTransactionExtensionCloseDTO;
import org.mall.modules.pojo.pay.transaction.PayTransactionBO;
import org.mall.modules.pojo.pay.transaction.PayTransactionGetDTO;
import org.mall.modules.pojo.pay.transaction.PayTransactionSubmitBO;
import org.mall.modules.pojo.pay.transaction.PayTransactionSubmitDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import static org.mall.common.api.vo.CommonResult.success;

@RestController
@RequestMapping("/users/transaction")
@Api("【用户】支付交易 API")
public class UsersPayTransactionController {

    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    AppMessageService appMessageService;
   @Autowired
    private PayTransactionService payTransactionService;
   @Autowired
   @Qualifier("transactionService")
   private WxPayService wxPayService;
   @Autowired
   private PayNotifyServiceImpl payNotifyService;

   @Autowired
   private DefaultMQProducer defaultMQProducer;
   @Autowired
   private AlipayClient alipayClient;

    @GetMapping("/get")
    @ApiOperation("获得支付交易")
    public CommonResult<PayTransactionBO> get(PayTransactionGetDTO payTransactionGetDTO) {

        payTransactionGetDTO.setUserId(JwtUtil.getUserIdByToken());
        return success(payTransactionService.getTransaction(payTransactionGetDTO));
    }

    @PostMapping("/submit")
    @ApiOperation("提交支付交易")
    public CommonResult<PayTransactionSubmitBO> submit(HttpServletRequest request,
                                                       @RequestBody PayTransactionSubmitDTO payTransactionSubmitDTO) {
        payTransactionSubmitDTO.setCreateIp(HttpUtil.getIp(request));
        // 提交支付提交
        return success(payTransactionService.submitTransaction(payTransactionSubmitDTO));
    }

    @PostMapping("/notify/wx/order")
    public String wxPaySuccess(@RequestBody String xmlData) throws IOException {
        logger.info("[WxPaySuccess][被回调]");
        payTransactionService.updateTransactionPaySuccess(PayChannelEnum.WEIXIN_APP.getId(), xmlData);
        AppMessageDTO appMessageDTO = new AppMessageDTO();
        appMessageDTO.setContent("您于"+DateUtils.formatDate(new Date())+"支付成功");
        appMessageDTO.setTitle("支付");
        appMessageDTO.setCreator("");
        appMessageDTO.setType(AppMessageTypeEnum.PAYMENT_NOTICE.getValue());
        appMessageDTO.setReceiver(JwtUtil.getUserIdByToken());
        appMessageDTO.setTemplateId(1);
        appMessageDTO.setCreateTime(DateUtils.getDate());
        appMessageDTO.setEntitiesId("");
        appMessageService.sendAppMessageToUser(appMessageDTO);
        return WxPayNotifyResponse.success("成功");
    }
    @PostMapping("/notify/ali/order")
    public String aliPaySuccess(HttpServletRequest request){
        logger.info("[aliPaySuccess][被回调]");
        Map<String,String> params = new HashMap<String,String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        boolean flag = false;
        try {
            flag = AlipaySignature.rsaCertCheckV1(params, "", "","RSA2");
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        if (flag){
            try {
                payTransactionService.updateTransactionPaySuccess(PayChannelEnum.ALIPAY.getId(), JacksonUtils.toJSONString(params));

            }catch (Exception e){
                logger.error("支付宝回调接口失败,参数信息:{}",JacksonUtils.toJSONString(params));
            }
        }
        return "success";

    }

    @ApiOperation(value = "查询订单")
    @GetMapping("/queryOrder")
    public CommonResult<?> queryOrder(@RequestParam String orderId)
            throws WxPayException {

        PayTransactionBO transactionBO=payTransactionService.getTransactionByOrderId(orderId);
        if (transactionBO==null){
            return CommonResult.error("订单不存在");
        }
        PayTransactionExtensionDO extensionDO=payTransactionService.getTransactionExtensionByIdAndStatus(transactionBO.getExtensionId(),PayTransactionStatusEnum.WAITING.getValue());
        if (PayChannelEnum.WEIXIN_APP.getId().equals(extensionDO.getPayChannel())){
            WxPayOrderQueryResult wxPayOrderQueryResult= wxPayService.queryOrder("", extensionDO.getTransactionCode());
            if ("SUCCESS".equals(wxPayOrderQueryResult.getReturnCode())&& "SUCCESS".equals(wxPayOrderQueryResult.getResultCode())){
                if ("SUCCESS".equals(wxPayOrderQueryResult.getTradeState())){
                    PayTransactionDO transactionDO=payTransactionService.selectById(extensionDO.getTransactionId());
                    if (transactionDO!=null&&!transactionDO.getStatus().equals(PayTransactionStatusEnum.SUCCESS.getValue())){
                        PayNotifyTaskDO payTransactionNotifyTask = payNotifyService.createBasePayNotifyTaskDO(transactionDO.getAppId(), transactionDO.getNotifyUrl())
                                .setType(PayNotifyType.TRANSACTION.getValue());
                        payNotifyService.sendNotifyMessage(payTransactionNotifyTask);
                    }
                }
            }else {
                if (extensionDO==null){
                    return CommonResult.success(wxPayOrderQueryResult);
                }
                PayTransactionExtensionCloseDTO dto=new PayTransactionExtensionCloseDTO();
                dto.setTransactionCode(extensionDO.getTransactionCode());
                defaultMQProducer.setProducerGroup("pay-provider-group-" + CommonConstant.MALL_CLOSE_EXTENTRANSACTION);
                try {
                    Message sendMsg = new Message(CommonConstant.MALL_CLOSE_EXTENTRANSACTION,
                            "rocketTag",
                            "", JacksonUtils.toJSONString(dto).getBytes());
                    defaultMQProducer.send(sendMsg);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return CommonResult.success(wxPayOrderQueryResult);

        }else if (PayChannelEnum.ALIPAY.getId().equals(extensionDO.getPayChannel())){
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            JSONObject jsonObject=new JSONObject();
            jsonObject.put("out_trade_no",extensionDO.getTransactionCode());
            request.setBizContent(jsonObject.toJSONString());
            try {
                AlipayTradeQueryResponse response = alipayClient.execute(request);
                if (response.isSuccess()){
                    if ("TRADE_SUCCESS".equals(response.getTradeStatus())){
                        PayTransactionDO transactionDO=payTransactionService.selectById(extensionDO.getTransactionId());
                        if (transactionDO!=null&&!transactionDO.getStatus().equals(PayTransactionStatusEnum.SUCCESS.getValue())){
                            PayNotifyTaskDO payTransactionNotifyTask = payNotifyService.createBasePayNotifyTaskDO(transactionDO.getAppId(), transactionDO.getNotifyUrl())
                                    .setType(PayNotifyType.TRANSACTION.getValue());
                            payNotifyService.sendNotifyMessage(payTransactionNotifyTask);
                        }
                    }
                }else {
                    if ("ACQ.TRADE_NOT_EXIST".equals(response.getSubCode())){
                        return CommonResult.error("查询的订单不存在");
                    }
                    return CommonResult.error("查询失败，订单异常"+response.getSubMsg());
                }
            } catch (AlipayApiException e) {
                e.printStackTrace();
            }


            return CommonResult.ok();
        }
        return CommonResult.ok();

    }

    @ApiOperation(value = "关闭订单")
    @GetMapping("/closeOrder/{orderId}")
    public WxPayOrderCloseResult closeOrder(@PathVariable String orderId) throws WxPayException {
        return wxPayService.closeOrder(orderId);
    }
    /**
     * <pre>
     * 微信支付-查询退款
     * 应用场景：
     *  提交退款申请后，通过调用该接口查询退款状态。退款有一定延时，用零钱支付的退款20分钟内到账，
     *  银行卡支付的退款3个工作日后重新查询退款状态。
     * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
     * 接口链接：https://api.mch.weixin.qq.com/pay/refundquery
     * </pre>
     * 以下四个参数四选一
     *
     * @param transactionId 微信订单号
     * @param outTradeNo    商户订单号
     * @param outRefundNo   商户退款单号
     * @param refundId      微信退款单号
     * @return 退款信息
     */
    @ApiOperation(value = "退款查询")
    @GetMapping("/refundQuery")
    public Object refundQuery(@RequestParam(required = false) String transactionId,
                                              @RequestParam(required = false) String outTradeNo,
                                              @RequestParam(required = false) String outRefundNo,
                                              @RequestParam(required = false) String refundId)
            throws WxPayException {
        return wxPayService.refundQuery(transactionId, outTradeNo, outRefundNo, refundId);
    }
}
